/* 
 * Quechua - the lightweight data mining framework
 *
 * Copyright (C) 2012 Marek Denis <quechua@octogan.net>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#ifndef MODULES_H
#define	MODULES_H

#include <cassert>

#include <glibmm/init.h>
#include <glibmm/module.h>

#include "types.h"
#include "log.h"
#include "interface.h"

class Module {
 private:
    string_t name;
    string_t path;
    g_module *module;
 public:
    Module(const string_t& name, const string_t& path,g_module* module);
    virtual ~Module(); 

    const string_t& get_name() const;
    const string_t& get_path() const;
    bool get_symbol(const string_t& symbol_name,void*& symbol);
    g_module* get_module() const;

};

typedef std::map<string_t,Module*> map_module;
typedef map_module::iterator map_module_it;


Channel* const register_flow_in_channels(const setting_t&,Workflow*,
                               channels_map* channels);
void unregister_flow_from_channels(Workflow* flow, Channel* channel);
Logger* const register_flow_in_loggers(const setting_t& flow_settings,Workflow* flow, 
                              loggers_map* loggers);
void unregister_flow_from_loggers(Workflow* flow, Logger* logger);


class Modules {
 public:
    Modules(const string_t& path_prefix_) : path_prefix(path_prefix_)
    {};
    virtual ~Modules() {
        LOG(INFO) << "Destroying modules";
        map_module::iterator it,end;
        it = modules.begin();
        end =modules.end();
        for(;it!=end;++it){
            delete it->second;
        }
        modules.clear();
    }

    bool load_modules(const configuration_t& config);
    bool load_components(const configuration_t& config);
    bool add_module(const string_t& mod_name, const string_t& library_file);
    bool module_loaded(const string_t& modname);
    
    Algorithm* load_algorithm(const string_t& algorithm_name,
                              const setting_t& algorithm_settings);
    Processor* load_processor(const string_t& processor_name,
                              const setting_t& processor_settings);
    size_t size();

 private:
    string_t path_prefix;
    map_module modules;

    Module* load_module_s(const string_t& kName);

    bool load_channels(const setting_t& channel_settings);
    bool load_loggers(const setting_t& logger_settings);
    bool load_workflows(const setting_t& flow_settings);
};

#endif	/* MODULES_H */

